package com.cw.jeeyt.service.impl.api;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.cw.base.common.model.enums.EnumDatabaseType;
import com.cw.jeeyt.common.enums.EnumExportScriptKind;
import com.cw.jeeyt.service.intf.api.ApiDataGenenratorService;
import com.cw.jeeyt.common.CommonUtil;
import com.cw.jeeyt.common.utils.DateUtils;
import com.cw.jeeyt.common.utils.FileUtils;
import com.cw.jeeyt.common.utils.StringUtil;
import com.cw.jeeyt.service.bo.api.ApiDatabaseInsertScriptVo;
import com.cw.jeeyt.service.bo.api.ApiDatabaseScriptConfigBo;
import com.cw.jeeyt.service.bo.api.ApiDatabaseTableScriptVo;
import com.cw.jeeyt.service.bo.api.ApiInsertScriptVo;
import com.cw.jeeyt.service.bo.api.ApiTableBo;
import com.cw.jeeyt.service.bo.api.ApiTableColumnBo;
import com.cw.jeeyt.service.bo.api.ApiTableIndexBo;
import com.cw.jeeyt.service.bo.api.ApiTableScriptBo;
import com.cw.jeeyt.core.util.SessionUtil;
import com.cw.jeeyt.dao.intf.api.ApiDatabaseDocDao;
import com.cw.jeeyt.dao.intf.api.ApiTableAbbreviationDao;
import com.cw.jeeyt.dao.model.api.ApiDatabaseDocDo;
import com.cw.jeeyt.dao.model.api.ApiTableAbbreviationDo;
import com.cw.lang.common.utils.CollectionUtil;
import com.cw.lang.common.utils.DateUtil;

/**
 * 数据库信息读取
 *
 * @author: chenw
 * @create: 2018-10-26 21:40
 */
@Service
public class ApiDataGenenratorServiceImpl implements ApiDataGenenratorService {

    public static final int BUFSIZE = 1024 * 8;
    private static Logger logger = LoggerFactory.getLogger(ApiDataGenenratorServiceImpl.class);
    //数据脚本输出全路径
    private static String outputInsertScriptPath;
    //建表脚本输出全路径
    private static String outputCreateScriptPath;
    @Value("${database.export.outputPath}")
    private String databaseExportOutputPath;
    @Autowired
    private ApiDatabaseDocDao apiDatabaseDocDao;
    @Autowired
    private ApiTableAbbreviationDao apiTableAbbreviationDao;

    /**
     * 获取数据库连接信息
     *
     * @return
     * @throws SQLException
     */
    private static Connection getDBConnection(ApiDatabaseDocDo apiDatabaseDocModel) throws Exception {

        Connection conn = null;
        try {
            Class.forName(apiDatabaseDocModel.getJdbcDriverClass())
                .newInstance();
            conn = DriverManager.getConnection(apiDatabaseDocModel.getJdbcUrl(), apiDatabaseDocModel.getJdbcUserName(),
                apiDatabaseDocModel.getJdbcUserPassword());
            if (logger.isDebugEnabled()) {
                logger.debug("Succeed to get a DB connection: " + conn);
            }
        } catch (Exception e) {
            logger.error("Error when load jdbc driver", e);
            throw new Exception(e.getMessage());
        }
        return conn;
    }

    public static void main(String[] args) throws Exception {
        //FileUtils.unionDirectoryFiles("D:/excel/output/temp/outputFileName.txt", "D:/excel/output/temp", "utf-8");
        String[] files = new String[2];
        files[0] = "D:/excel/output/temp/a.txt";
        files[1] = "D:/excel/output/temp/b.txt";
        mergeFiles("D:/excel/output/temp/outputFileName.txt", files);
    }

    public static void mergeFiles(String outFile, String[] files) {
        FileChannel outChannel = null;
        try {
            outChannel = new FileOutputStream(outFile).getChannel();

            for (String f : files) {
                Charset charset = Charset.forName("utf-8");
                CharsetDecoder chdecoder = charset.newDecoder();
                CharsetEncoder chencoder = charset.newEncoder();
                FileChannel fc = new FileInputStream(f).getChannel();
                ByteBuffer bb = ByteBuffer.allocate(BUFSIZE);
                CharBuffer charBuffer = chdecoder.decode(bb);
                ByteBuffer nbuBuffer = chencoder.encode(charBuffer);
                while (fc.read(nbuBuffer) != -1) {
                    bb.flip();
                    nbuBuffer.flip();
                    outChannel.write(nbuBuffer);
                    bb.clear();
                    nbuBuffer.clear();
                }
                fc.close();
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        } finally {
            try {
                if (outChannel != null) {
                    outChannel.close();
                }
            } catch (IOException ignore) {
            }
        }
    }

    /**
     * 生成数据库数据
     *
     * @param databaseId
     * @param tablePrefix
     * @return
     * @throws Exception
     */
    @Override
    public List<ApiTableBo> generateData(Long databaseId, String tablePrefix) throws Exception {
        List<ApiTableBo> apiTableExcels = new ArrayList<>();
        Connection connection = null;
        try {
            ApiDatabaseDocDo apiDatabaseDocModel = apiDatabaseDocDao.getById(databaseId);
            if (apiDatabaseDocModel == null) {
                throw new Exception("数据库信息获取失败");
            }
            connection = getDBConnection(apiDatabaseDocModel);
            String databaseCode = apiDatabaseDocModel.getDatabaseCode();
            //读取表信息
            String queryTableSql
                = "select table_name tableCode,table_comment tableName from information_schema.tables where table_schema = ?";
            PreparedStatement pstmt = connection.prepareStatement(queryTableSql);
            pstmt.setString(1, apiDatabaseDocModel.getDatabaseCode());
            ResultSet rs = pstmt.executeQuery();
            int i = 1;
            while (rs.next()) {
                String tableCode = rs.getString("tableCode");
                String tableName = rs.getString("tableName");
                if (StringUtils.isNotEmpty(tablePrefix)) {
                    if (!tableCode.startsWith(tablePrefix.toLowerCase())) {
                        continue;
                    }
                }
                logger.info("开始获取{}【{}】表结构信息", tableCode, tableName);
                ApiTableBo apiTableExcel = new ApiTableBo();
                apiTableExcel.setDatabaseCode(databaseCode);
                apiTableExcel.setTableNum(i);
                apiTableExcel.setTableCode(tableCode);
                apiTableExcel.setTableDesc(tableName);
                // if (StringUtils.isEmpty(tableName)) {
                //     apiTableExcel.setTableDesc(tableCode);
                // }
                //查询表字段信息
                StringBuilder queryColumnSql = new StringBuilder(
                    "select distinct column_name columnCode, data_type columnType, "
                        + "column_comment columnName,character_maximum_length columnLength,numeric_precision numericPercision,"
                        + "numeric_scale numericScale,column_key isPrimaryKey,is_nullable isNullable,column_default columnDefault ,extra autoIncrement from information_schema.columns where table_name = ? and table_schema=?");
                PreparedStatement columnPstmt = connection.prepareStatement(queryColumnSql.toString());
                columnPstmt.setString(1, tableCode);
                columnPstmt.setString(2, apiDatabaseDocModel.getDatabaseCode());
                ResultSet rsColumn = columnPstmt.executeQuery();
                List<ApiTableColumnBo> dataBaseColumnList = new ArrayList<ApiTableColumnBo>();
                while (rsColumn.next()) {
                    ApiTableColumnBo apiTableColumnExcel = new ApiTableColumnBo();
                    //列编码
                    String columnCode = rsColumn.getString("columnCode");
                    //列名称
                    String columnName = rsColumn.getString("columnName");
                    //是否为空
                    String isNullable = rsColumn.getString("isNullable");
                    //列长度
                    String columnLength = rsColumn.getString("columnLength");
                    //默认值
                    String columnDefault = rsColumn.getString("columnDefault");
                    //数值长度
                    String numericPercision = rsColumn.getString("numericPercision");
                    //小数位长度
                    String numericScale = rsColumn.getString("numericScale");
                    //自增
                    String autoIncrement = rsColumn.getString("autoIncrement");
                    if (StringUtils.isNotEmpty(columnCode)) {
                        columnCode = columnCode.toLowerCase();
                    }
                    String columnType = rsColumn.getString("columnType");
                    apiTableColumnExcel.setColumnCode(columnCode);
                    apiTableColumnExcel.setColumnComment(columnName);
                    apiTableColumnExcel.setColumnType(columnType);
                    apiTableColumnExcel.setColumnDesc(columnName);
                    apiTableColumnExcel.setColumnIsNull("NO".equals(isNullable) ? "否" : "是");
                    apiTableColumnExcel.setAutoIncrement(false);
                    if ("auto_increment".equals(autoIncrement)) {
                        apiTableColumnExcel.setAutoIncrement(true);
                    }
                    if (StringUtils.isNotEmpty(columnLength)) {
                        if (!columnType.contains("text") && !columnType.contains("blob")) {
                            apiTableColumnExcel.setColumnLength(columnLength);
                        }
                    } else {
                        if (StringUtils.isNotEmpty(numericPercision) && !columnType.contains("text")
                            && !columnType.contains("blob")) {
                            if (StringUtils.isNotEmpty(numericScale)) {
                                if (!numericScale.equals("0")) {
                                    apiTableColumnExcel.setColumnLength(numericPercision + "," + numericScale);
                                } else {
                                    apiTableColumnExcel.setColumnLength(numericPercision);
                                }
                            }
                        }
                    }
                    apiTableColumnExcel.setDefaultVal(columnDefault);
                    dataBaseColumnList.add(apiTableColumnExcel);
                }
                apiTableExcel.setColumnList(dataBaseColumnList);
                //查询索引信息
                StringBuilder sqlBuf = new StringBuilder(
                    "SELECT TABLE_SCHEMA AS TABLE_CAT, NULL AS TABLE_SCHEM, TABLE_NAME, NON_UNIQUE,");
                sqlBuf.append(
                    "TABLE_SCHEMA AS INDEX_QUALIFIER, INDEX_NAME,INDEX_TYPE, SEQ_IN_INDEX AS ORDINAL_POSITION, COLUMN_NAME, SUB_PART, ");
                sqlBuf.append(
                    "COLLATION AS ASC_OR_DESC, CARDINALITY, NULL AS PAGES, NULL AS FILTER_CONDITION FROM INFORMATION_SCHEMA.STATISTICS WHERE ");
                sqlBuf.append("TABLE_NAME = ? and table_schema=?");
                PreparedStatement indexPstmt = connection.prepareStatement(sqlBuf.toString());
                indexPstmt.setString(1, tableCode);
                indexPstmt.setString(2, databaseCode);
                ResultSet rsIndex = indexPstmt.executeQuery();
                List<ApiTableIndexBo> apiTableIndexs = new ArrayList<>();
                Map<String, List<ApiTableIndexBo>> indexMap = new HashMap<>();
                while (rsIndex.next()) {
                    ApiTableIndexBo apiTableIndexBo = new ApiTableIndexBo();
                    String indexName = rsIndex.getString("INDEX_NAME");
                    String indexType = rsIndex.getString("INDEX_TYPE");
                    String colnumName = rsIndex.getString("COLUMN_NAME");
                    String subPart = rsIndex.getString("SUB_PART");
                    Boolean unique = !rsIndex.getBoolean("NON_UNIQUE");// 非唯一索引
                    apiTableIndexBo.setIndexUnique(unique == true ? "是" : "否");
                    apiTableIndexBo.setIndexType(indexType);
                    apiTableIndexBo.setIndexColumns(colnumName);
                    apiTableIndexBo.setIndexCode(indexName);
                    apiTableIndexBo.setSubPart(subPart);
                    apiTableIndexs.add(apiTableIndexBo);
                    if (indexMap.containsKey(indexName)) {
                        List<ApiTableIndexBo> indexBos = indexMap.get(indexName);
                        indexBos.add(apiTableIndexBo);
                        indexMap.put(indexName, indexBos);
                    } else {
                        List<ApiTableIndexBo> indexBos = new ArrayList<>();
                        indexBos.add(apiTableIndexBo);
                        indexMap.put(indexName, indexBos);
                    }
                }
                apiTableExcel.setIndexMap(indexMap);
                apiTableExcels.add(apiTableExcel);
                i++;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e.getMessage());
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
        return apiTableExcels;
    }

    /**
     * 生成建表脚本
     *
     * @param apiTables
     * @throws Exception
     */
    @Override
    public void generateTableScript(String scriptPath, List<ApiTableBo> apiTables,
        ApiDatabaseScriptConfigBo scriptConfigBo, EnumDatabaseType databaseType) throws Exception {
        if (CollectionUtils.isEmpty(apiTables)) {
            return;
        }
        ApiDatabaseDocDo apiDatabaseDocModel = apiDatabaseDocDao.getById(scriptConfigBo.getDatabaseId());
        if (apiDatabaseDocModel == null) {
            throw new Exception("数据库信息获取失败");
        }
        //如果表前缀为空，则导出数据库所有的建表sql
        String tablePrefix = scriptConfigBo.getTablePrefix();
        List<String> tablePrefixs = getTablePrefixs(tablePrefix, apiTables);
        int i = 1;
        for (String prefix : tablePrefixs) {
            outputCreateScriptPath = scriptPath + File.separator + EnumExportScriptKind.CREATE_SCRIPT.getDescription()
                + File.separator + i + "-DDL-" + apiDatabaseDocModel.getDatabaseCode() + "-" + prefix + "-"
                + scriptConfigBo.getScriptVersion() + ".sql";
            FileUtils.deleteFile(outputCreateScriptPath);
            FileUtils.createFile(outputCreateScriptPath);
            ApiDatabaseTableScriptVo apiDatabaseTableScriptVo = new ApiDatabaseTableScriptVo();
            apiDatabaseTableScriptVo.setAuthor(scriptConfigBo.getAuthor());
            apiDatabaseTableScriptVo.setExportDate(DateUtil.getDate(new Date(), "yyyy/MM/dd"));
            apiDatabaseTableScriptVo.setExportComment(scriptConfigBo.getExportComment());
            apiDatabaseTableScriptVo.setDatabaseId(scriptConfigBo.getDatabaseId());
            if (databaseType == EnumDatabaseType.ORACLE) {
                apiDatabaseTableScriptVo.setTableSpace(scriptConfigBo.getTableSpace());
                apiDatabaseTableScriptVo.setIndexSpace(scriptConfigBo.getIndexSpace());
                apiDatabaseTableScriptVo.setDatabaseOwner(scriptConfigBo.getDatabaseOwner());
            }
            List<ApiTableScriptBo> apiTableScripts = new ArrayList<>();
            for (ApiTableBo apiTableBo : apiTables) {
                if (apiTableBo.getTableCode()
                    .startsWith(prefix.toLowerCase())) {
                    ApiTableScriptBo apiTableScriptBo = new ApiTableScriptBo();
                    apiTableScriptBo.setTableCode(apiTableBo.getTableCode());
                    apiTableScriptBo.setTableName(apiTableBo.getTableDesc());
                    apiTableScriptBo.setColumnList(apiTableBo.getColumnList());
                    apiTableScriptBo.setIndexMap(apiTableBo.getIndexMap());
                    apiTableScripts.add(apiTableScriptBo);
                }
            }
            apiDatabaseTableScriptVo.setApiTableScripts(apiTableScripts);
            writeTableScriptToFile(apiDatabaseTableScriptVo, databaseType);
            i++;
        }
    }

    /**
     * 建表脚本输出到文件中
     *
     * @param scriptVo
     */
    private void writeTableScriptToFile(ApiDatabaseTableScriptVo scriptVo, EnumDatabaseType databaseType)
    throws IOException {
        //输出头部内容
        String author = scriptVo.getAuthor();
        String exportComment = scriptVo.getExportComment();
        String exportDate = scriptVo.getExportDate();
        StringBuilder sb = new StringBuilder("");
        sb.append("-- ----------------------------\r\n");
        sb.append("-- 更新时间:" + exportDate + "\r\n");
        sb.append("-- 负责人:" + author + "\r\n");
        sb.append("-- 更新内容:" + exportComment + "\r\n");
        sb.append("-- ----------------------------");
        sb.append("\r\n");
        sb.append("\r\n");
        if (databaseType == EnumDatabaseType.MYSQL) {
            sb.append("-- 关闭自动提交\r\n");
            sb.append("set autocommit = 0;\r\n");
        }
        FileUtils.mergeContentToFile(outputCreateScriptPath, sb.toString());
        List<ApiTableScriptBo> tableScriptBos = scriptVo.getApiTableScripts();
        if (CollectionUtil.isNotEmpty(tableScriptBos)) {
            for (ApiTableScriptBo apiTableScriptBo : tableScriptBos) {
                sb = new StringBuilder("");
                sb.append("-- ----------------------------\r\n");
                sb.append("-- Table structure for " + apiTableScriptBo.getTableCode()
                    .toUpperCase() + ";\r\n");
                sb.append("-- ----------------------------\r\n");
                //组装头部信息
                formatHeaderInfo(sb, databaseType, apiTableScriptBo.getTableCode(), scriptVo.getDatabaseOwner());
                if (databaseType == EnumDatabaseType.MYSQL) {
                    sb.append("create table `" + apiTableScriptBo.getTableCode() + "` (\r\n");
                } else if (databaseType == EnumDatabaseType.ORACLE) {
                    sb.append("CREATE TABLE \"" + apiTableScriptBo.getTableCode()
                        .toUpperCase() + "\" (\r\n");
                }
                boolean indexEmpty = false;
                if (CollectionUtil.isEmpty(apiTableScriptBo.getIndexMap())) {
                    indexEmpty = true;
                }
                //组装字段信息
                formatColumnInfo(sb, apiTableScriptBo.getColumnList(), indexEmpty, databaseType);
                if (databaseType == EnumDatabaseType.MYSQL) {
                    //组装索引信息
                    formatIndexInfo(sb, apiTableScriptBo.getIndexMap());
                }
                sb.append(")");
                if (databaseType == EnumDatabaseType.MYSQL) {
                    sb.append("COMMENT = '" + apiTableScriptBo.getTableName() + "';\r\n");
                } else if (databaseType == EnumDatabaseType.ORACLE) {
                    sb.append("\r\n");
                    formatOracleTableSpace(sb, scriptVo.getTableSpace());
                    formatOracleCommentInfo(sb, scriptVo.getDatabaseOwner(), apiTableScriptBo.getTableCode(),
                        apiTableScriptBo.getColumnList());
                    formatOracleTableCommentInfo(sb, scriptVo.getDatabaseOwner(), apiTableScriptBo.getTableCode(),
                        apiTableScriptBo.getTableName());
                    sb.append("\r\n");
                    sb.append("\r\n");
                    sb.append("\r\n");
                    formatOraclePrimaryKeyInfo(scriptVo.getDatabaseId(), sb, scriptVo.getDatabaseOwner(),
                        apiTableScriptBo.getTableCode(), apiTableScriptBo.getIndexMap());
                    sb.append("\r\n");
                    sb.append("\r\n");
                    formatOracleIndexInfo(sb, scriptVo.getDatabaseOwner(), apiTableScriptBo.getTableCode(),
                        scriptVo.getIndexSpace(), apiTableScriptBo.getIndexMap());
                    sb.append("\r\n");
                    sb.append("\r\n");
                    sb.append("\r\n");
                }
                FileUtils.mergeContentToFile(outputCreateScriptPath, sb.toString());
            }
        }
        sb = new StringBuilder("");
        sb.append("\r\n");
        sb.append("\r\n");
        sb.append("commit;");
        FileUtils.mergeContentToFile(outputCreateScriptPath, sb.toString());
    }

    private void formatOracleTableCommentInfo(StringBuilder sb, String databaseOwner, String tableCode,
        String tableName) {
        sb.append("COMMENT ON TABLE ");
        sb.append(databaseOwner);
        sb.append(".");
        sb.append("\"" + tableCode.toUpperCase() + "\"");
        sb.append(" IS '" + tableName + "';\r\n");
    }

    /**
     * Oracle索引信息
     *
     * @param sb
     * @param indexMap
     */
    private void formatOracleIndexInfo(StringBuilder sb, String databaseOwner, String tableCode, String indexSpace,
        Map<String, List<ApiTableIndexBo>> indexMap) {
        Map<String, List<ApiTableIndexBo>> normalIndexMap = getNormalIndexMap(indexMap);
        if (CollectionUtil.isNotEmpty(normalIndexMap)) {
            Iterator it = normalIndexMap.keySet()
                .iterator();
            while (it.hasNext()) {
                String key = (String) it.next();
                boolean isUnique = false;
                //先判断是否唯一索引
                for (ApiTableIndexBo apiTableIndex : normalIndexMap.get(key)) {
                    if (apiTableIndex.getIndexUnique()
                        .equals("是")) {
                        isUnique = true;
                        break;
                    }
                }
                if (isUnique) {
                    sb.append("CREATE UNIQUE INDEX " + databaseOwner + ".\"" + key.toUpperCase() + "\"\r\n");
                } else {
                    sb.append("CREATE INDEX " + databaseOwner + ".\"" + key.toUpperCase() + "\"\r\n");
                }
                sb.append(" ON " + databaseOwner + "." + tableCode.toUpperCase());
                sb.append("(");
                int i = 0;
                for (ApiTableIndexBo apiTableIndex : normalIndexMap.get(key)) {
                    if (i == 0) {
                        sb.append("\"" + apiTableIndex.getIndexColumns()
                            .toUpperCase() + "\" ASC");
                    } else {
                        sb.append(",\"" + apiTableIndex.getIndexColumns()
                            .toUpperCase() + "\" ASC");
                    }
                    i++;
                }
                sb.append(")\r\n");
                sb.append(" LOGGING\r\n");
                sb.append(" TABLESPACE " + indexSpace + "\r\n");
                sb.append(" VISIBLE\r\n");
                sb.append("PCTFREE 10\r\n");
                sb.append("INITRANS 2\r\n");
                sb.append("STORAGE (\r\n");
                sb.append(" INITIAL 65536\r\n");
                sb.append(" NEXT 1048576\r\n");
                sb.append(" MINEXTENTS 1\r\n");
                sb.append(" MAXEXTENTS 2147483645\r\n");
                sb.append(" BUFFER_POOL DEFAULT\r\n");
                sb.append(");\r\n");
            }
        }
    }

    /**
     * 获取主键列表
     *
     * @param sb
     * @param indexMap
     * @param tableCode
     */
    private void formatOraclePrimaryKeyInfo(Long databaseId, StringBuilder sb, String tableOwner, String tableCode,
        Map<String, List<ApiTableIndexBo>> indexMap) {
        List<ApiTableIndexBo> primaryKeyList = getPrimaryIndexList(indexMap);
        if (CollectionUtil.isEmpty(primaryKeyList)) {
            return;
        }
        sb.append("-- ----------------------------\r\n");
        sb.append("-- Primary Key structure for table " + tableCode.toUpperCase() + "\r\n");
        sb.append("-- ----------------------------\r\n");
        int i = 0;
        String pkConstraint = getPkConstraint(databaseId, tableCode, primaryKeyList);
        if (pkConstraint.length() > 30) {
            pkConstraint = reGetPkConstraint(databaseId, tableCode, primaryKeyList);
        }
        sb.append("ALTER TABLE " + tableOwner + "." + tableCode.toUpperCase() + " ADD CONSTRAINT \""
            + pkConstraint.toUpperCase() + "\" PRIMARY KEY");
        sb.append("(");
        for (ApiTableIndexBo indexBo : primaryKeyList) {
            if (i == 0) {
                sb.append("\"" + indexBo.getIndexColumns()
                    .toUpperCase() + "\"");
            } else {
                sb.append(", \"" + indexBo.getIndexColumns()
                    .toUpperCase() + "\"");
            }
            i++;
        }
        sb.append(");\r\n");
    }

    /**
     * 主键约束长度超过30时,重新生成主键约束
     *
     * @param tableCode
     * @param primaryKeyList
     * @return
     */
    private String reGetPkConstraint(Long databaseId, String tableCode, List<ApiTableIndexBo> primaryKeyList) {
        String tableCodeAbridge = "";
        int length = 0;
        StringBuilder pkConstraint = new StringBuilder("PK_");
        length = length + 3;
        ApiTableAbbreviationDo checkDo = apiTableAbbreviationDao.findByTableCode(tableCode, databaseId);
        if (checkDo != null) {
            tableCodeAbridge = checkDo.getTableAbbreviation();
        } else {
            tableCodeAbridge = getTableCodeAbridge(tableCode);
        }
        pkConstraint.append(tableCodeAbridge);
        length = length + tableCodeAbridge.length();
        pkConstraint.append("_");
        length = length + 7;
        StringBuilder sb = new StringBuilder("");
        int i = 0;
        for (ApiTableIndexBo indexBo : primaryKeyList) {
            String indexCode = indexBo.getIndexColumns();
            if (indexCode.toUpperCase()
                .equals("TENANT_ID")) {
                continue;
            }
            if (i == 0) {
                sb.append(indexCode);
            } else {
                sb.append("_" + indexCode);
            }
            i++;
        }
        String subIndexCode = sb.substring(0, 30 - length + 1);
        pkConstraint.append(subIndexCode.replaceAll("_", ""));
        pkConstraint.append("_TNTID");
        return pkConstraint.toString();
    }

    /**
     * 获取主键约束
     *
     * @param primaryKeyList
     * @return
     */
    private String getPkConstraint(Long databaseId, String tableCode, List<ApiTableIndexBo> primaryKeyList) {
        String tableCodeAbridge = "";
        ApiTableAbbreviationDo checkDo = apiTableAbbreviationDao.findByTableCode(tableCode, databaseId);
        if (checkDo != null) {
            tableCodeAbridge = checkDo.getTableAbbreviation();
        } else {
            tableCodeAbridge = getTableCodeAbridge(tableCode);
        }
        StringBuilder pkConstraint = new StringBuilder("PK_");
        pkConstraint.append(tableCodeAbridge);
        pkConstraint.append("_");
        for (ApiTableIndexBo indexBo : primaryKeyList) {
            String indexCode = indexBo.getIndexColumns();
            if (indexCode.toUpperCase()
                .equals("TENANT_ID")) {
                continue;
            }
            pkConstraint.append(indexCode.replaceAll("_", "")
                .toUpperCase());
        }
        pkConstraint.append("_TNTID");
        return pkConstraint.toString();
    }

    /**
     * 获取表编码缩写
     *
     * @param tableCode
     * @return
     */
    private String getTableCodeAbridge(String tableCode) {
        StringBuilder sb = new StringBuilder("");
        String[] tableCodeFields = tableCode.toUpperCase()
            .split("_");
        for (String tableCodeField : tableCodeFields) {
            sb.append(tableCodeField.substring(0, 1));
        }
        return sb.toString();
    }

    /**
     * Oracle注释信息
     *
     * @param sb
     * @param databaseOwner
     * @param tableCode
     * @param columnList
     */
    private void formatOracleCommentInfo(StringBuilder sb, String databaseOwner, String tableCode,
        List<ApiTableColumnBo> columnList) {
        for (ApiTableColumnBo columnBo : columnList) {
            sb.append("COMMENT ON COLUMN ");
            sb.append(databaseOwner);
            sb.append(".");
            sb.append("\"" + tableCode.toUpperCase() + "\"");
            sb.append(".");
            sb.append("\"" + columnBo.getColumnCode()
                .toUpperCase() + "\" ");
            sb.append("IS '" + columnBo.getColumnDesc() + "';\r\n");
        }
    }

    /**
     * 生成Oracle表空间信息
     *
     * @param sb
     * @param tableSpace
     */
    private void formatOracleTableSpace(StringBuilder sb, String tableSpace) {
        sb.append("TABLESPACE " + tableSpace + "\r\n");
        sb.append("LOGGING" + "\r\n");
        sb.append("NOCOMPRESS" + "\r\n");
        sb.append("PCTFREE 10" + "\r\n");
        sb.append("INITRANS 1" + "\r\n");
        sb.append("STORAGE (" + "\r\n");
        sb.append("     BUFFER_POOL DEFAULT" + "\r\n");
        sb.append(")" + "\r\n");
        sb.append("PARALLEL 1" + "\r\n");
        sb.append("NOCACHE" + "\r\n");
        sb.append("DISABLE ROW MOVEMENT" + "\r\n");
        sb.append(";" + "\r\n");
    }

    /**
     * 组装头部信息
     *
     * @param sb
     * @param databaseType
     */
    private void formatHeaderInfo(StringBuilder sb, EnumDatabaseType databaseType, String tableCode,
        String databaseOwner) {
        if (databaseType == EnumDatabaseType.MYSQL) {
            sb.append("DROP TABLE IF EXISTS `" + tableCode + "`;\r\n");
        } else {
            sb.append("declare\r\n");
            sb.append("     num   number;\r\n");
            sb.append("begin\r\n");
            sb.append("     select count(1) into num from all_tables where TABLE_NAME = '" + tableCode.toUpperCase()
                + "' and OWNER='" + databaseOwner + "';\r\n");
            sb.append("     if   num=1   then\r\n");
            sb.append("         execute immediate 'drop table " + tableCode.toUpperCase() + "';\r\n");
            sb.append("     end   if;\r\n");
            sb.append("end;\r\n");
            sb.append("/\r\n");
        }
    }

    /**
     * 组装索引信息
     *
     * @param sb
     * @param indexMap
     */
    private void formatIndexInfo(StringBuilder sb, Map<String, List<ApiTableIndexBo>> indexMap) {
        if (CollectionUtil.isEmpty(indexMap)) {
            return;
        }
        List<ApiTableIndexBo> primaryIndexList = getPrimaryIndexList(indexMap);
        Map<String, List<ApiTableIndexBo>> normalIndexMap = getNormalIndexMap(indexMap);
        //先添加PRIMARY key,再添加 index
        int i = 0;
        String indexType = "";
        if (CollectionUtil.isNotEmpty(primaryIndexList)) {
            sb.append(" PRIMARY KEY (");
            for (ApiTableIndexBo apiTableIndex : primaryIndexList) {
                indexType = apiTableIndex.getIndexType();
                if (i == (primaryIndexList.size() - 1)) {
                    sb.append("`" + apiTableIndex.getIndexColumns()
                        .toLowerCase() + "`");
                } else {
                    sb.append("`" + apiTableIndex.getIndexColumns()
                        .toLowerCase() + "`,");
                }
                i++;
            }
            if (CollectionUtil.isNotEmpty(normalIndexMap)) {
                sb.append(") USING " + indexType + ",\r\n");
            } else {
                sb.append(") USING " + indexType + "\r\n");
            }
        }
        if (CollectionUtil.isNotEmpty(normalIndexMap)) {
            Iterator it = normalIndexMap.keySet()
                .iterator();
            Integer keySize = normalIndexMap.keySet()
                .size();
            i = 0;
            while (it.hasNext()) {
                String key = (String) it.next();
                List<ApiTableIndexBo> indexBos = normalIndexMap.get(key);
                int j = 0;
                sb.append(" KEY `" + key.toLowerCase() + "`");
                sb.append("(");
                for (ApiTableIndexBo apiTableIndex : normalIndexMap.get(key)) {
                    indexType = apiTableIndex.getIndexType();
                    if (j == (indexBos.size() - 1)) {
                        String subPart = apiTableIndex.getSubPart();
                        if (!StringUtil.isEmpty(subPart)) {
                            sb.append("`" + apiTableIndex.getIndexColumns()
                                .toLowerCase() + "`(" + subPart + ")");
                        } else {
                            sb.append("`" + apiTableIndex.getIndexColumns()
                                .toLowerCase() + "`");
                        }
                    } else {
                        String subPart = apiTableIndex.getSubPart();
                        if (!StringUtil.isEmpty(subPart)) {
                            sb.append("`" + apiTableIndex.getIndexColumns()
                                .toLowerCase() + "`(" + subPart + "),");
                        } else {
                            sb.append("`" + apiTableIndex.getIndexColumns()
                                .toLowerCase() + "`,");
                        }
                    }
                    j++;
                }
                sb.append(")");
                if (i == (keySize - 1)) {
                    sb.append(" USING " + indexType + "\r\n");
                } else {
                    sb.append(" USING " + indexType + ",\r\n");
                }
                i++;
            }
        }
    }

    /**
     * 获取索引信息
     *
     * @param indexMap
     * @return
     */
    private Map<String, List<ApiTableIndexBo>> getNormalIndexMap(Map<String, List<ApiTableIndexBo>> indexMap) {
        Map<String, List<ApiTableIndexBo>> normalIndexMap = new HashMap<>();
        Iterator iterator = indexMap.keySet()
            .iterator();
        //添加NormalIndex
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            List<ApiTableIndexBo> indexBos = indexMap.get(key);
            if (!"PRIMARY".equals(key)) {
                normalIndexMap.put(key, indexBos);
            }
        }
        return normalIndexMap;
    }

    /**
     * 获取主键列表
     *
     * @param indexMap
     * @return
     */
    private List<ApiTableIndexBo> getPrimaryIndexList(Map<String, List<ApiTableIndexBo>> indexMap) {
        Iterator iterator = indexMap.keySet()
            .iterator();
        //添加PRIMARY
        while (iterator.hasNext()) {
            String key = (String) iterator.next();
            List<ApiTableIndexBo> indexBos = indexMap.get(key);
            if ("PRIMARY".equals(key)) {
                return indexBos;
            }
        }
        return new ArrayList<>();
    }

    /**
     * 组装字段信息
     *
     * @param sb
     * @param columnList
     */
    private void formatColumnInfo(StringBuilder sb, List<ApiTableColumnBo> columnList, boolean indexEmpty,
        EnumDatabaseType databaseType) {
        if (CollectionUtil.isEmpty(columnList)) {
            return;
        }
        if (databaseType == EnumDatabaseType.ORACLE) {
            formatOracleColumnInfo(sb, columnList, indexEmpty);
            return;
        }
        int i = 0;
        for (ApiTableColumnBo apiTableColumn : columnList) {
            sb.append(" `" + apiTableColumn.getColumnCode() + "`");
            //字段类型、字段长度
            String columnLength = apiTableColumn.getColumnLength();
            if (StringUtils.isNotEmpty(columnLength)) {
                sb.append(" " + apiTableColumn.getColumnType() + "(" + apiTableColumn.getColumnLength() + ")");
            } else {
                sb.append(" " + apiTableColumn.getColumnType());
            }
            //是否为null
            if ("否".equals(apiTableColumn.getColumnIsNull())) {
                sb.append(" NOT NULL");
            }
            //是否自增
            if (apiTableColumn.isAutoIncrement()) {
                sb.append(" auto_increment");
            }
            //默认值
            String defaultValue = apiTableColumn.getDefaultVal();
            if (StringUtils.isNotEmpty(defaultValue)) {
                if (defaultValue.equalsIgnoreCase("current_timestamp")) {
                    sb.append(" DEFAULT " + defaultValue);
                } else {
                    sb.append(" DEFAULT '" + defaultValue + "'");
                }
            } else {
                if ((apiTableColumn.getColumnType()
                    .equals("datetime") || apiTableColumn.getColumnType()
                    .equals("date")) && "是".equals(apiTableColumn.getColumnIsNull())) {
                    sb.append(" DEFAULT NULL");
                }
            }
            if (StringUtils.isNotEmpty(apiTableColumn.getColumnDesc())) {
                sb.append(" COMMENT '" + apiTableColumn.getColumnDesc() + "'");
            }
            if (i != columnList.size() - 1) {
                sb.append(",\r\n");
            } else {
                if (!indexEmpty) {
                    sb.append(",\r\n");
                } else {
                    sb.append("\r\n");
                }
            }
            i++;
        }

    }

    /**
     * 生成数据脚本 insert
     *
     * @param apiTables
     * @throws Exception
     */
    @Override
    public void generateInsertScript(String scriptPath, List<ApiTableBo> apiTables,
        ApiDatabaseScriptConfigBo scriptConfigBo, EnumDatabaseType databaseType) throws Exception {
        if (CollectionUtils.isEmpty(apiTables)) {
            return;
        }
        ApiDatabaseDocDo apiDatabaseDocModel = apiDatabaseDocDao.getById(scriptConfigBo.getDatabaseId());
        if (apiDatabaseDocModel == null) {
            throw new Exception("数据库信息获取失败");
        }
        //如果表前缀为空，则导出数据库所有的建表sql
        String tablePrefix = scriptConfigBo.getTablePrefix();
        List<String> tablePrefixs = getTablePrefixs(tablePrefix, apiTables);
        Connection connection = null;
        try {
            connection = getDBConnection(apiDatabaseDocModel);
            int i = 1;
            for (String prefix : tablePrefixs) {
                outputInsertScriptPath = scriptPath + File.separator
                    + EnumExportScriptKind.INSERT_SCRIPT.getDescription() + File.separator + i + "-DML-"
                    + apiDatabaseDocModel.getDatabaseCode() + "-" + prefix + "-" + scriptConfigBo.getScriptVersion()
                    + ".sql";
                FileUtils.deleteFile(outputInsertScriptPath);
                FileUtils.createFile(outputInsertScriptPath);
                ApiDatabaseInsertScriptVo scriptVo = new ApiDatabaseInsertScriptVo();
                scriptVo.setAuthor(scriptConfigBo.getAuthor());
                scriptVo.setExportComment(scriptConfigBo.getExportComment());
                scriptVo.setExportDate(DateUtil.getDate(new Date(), "yyyy/MM/dd"));
                //生成头部信息
                writeHeaderContent(scriptVo, databaseType);
                Map<String, Object> extraLongObj = null;
                //读取表信息
                for (ApiTableBo apiTableBo : apiTables) {
                    String tableCode = apiTableBo.getTableCode();
                    if (!tableCode.startsWith(prefix)) {
                        continue;
                    }
                    ApiInsertScriptVo insertScriptVo = new ApiInsertScriptVo();
                    logger.info("生成{}表信息", tableCode);
                    String tableName = apiTableBo.getTableDesc();
                    insertScriptVo.setTableCode(tableCode);
                    insertScriptVo.setTableName(tableName);
                    StringBuilder queryInfoSb = new StringBuilder("select ");
                    int ii = 0;
                    //查询表字段信息
                    for (ApiTableColumnBo apiTableColumnBo : apiTableBo.getColumnList()) {
                        //组装查询字段
                        LinkedList<String> columnList = new LinkedList<>();
                        //列编码
                        String columnCode = apiTableColumnBo.getColumnCode();
                        if (StringUtils.isNotEmpty(columnCode)) {
                            columnCode = columnCode.toLowerCase();
                        }
                        columnList.add(columnCode);
                        if (ii == 0) {
                            queryInfoSb.append("`" + columnCode + "`");
                        } else {
                            queryInfoSb.append(",`" + columnCode + "`");
                        }
                        ii++;
                    }
                    queryInfoSb.append(" from " + tableCode);
                    ResultSet rsTableInfo = connection.createStatement()
                        .executeQuery(queryInfoSb.toString());
                    boolean insertFlag = true;
                    StringBuilder insertScripts = new StringBuilder("");
                    while (rsTableInfo.next()) {
                        extraLongObj = new HashMap<>();
                        if (insertFlag) {
                            insertScripts.append("\r\n");
                            if (databaseType == EnumDatabaseType.MYSQL) {
                                insertScripts.append("TRUNCATE TABLE `" + tableCode + "`;\r\n");
                            }
                        }
                        insertFlag = false;
                        StringBuilder insertScript = new StringBuilder("");
                        if (databaseType == EnumDatabaseType.MYSQL) {
                            insertScript.append("insert into `" + tableCode + "` (");
                        } else if (databaseType == EnumDatabaseType.ORACLE) {
                            StringBuilder extraLong = new StringBuilder("");
                            boolean hasExtraData = false;
                            for (ApiTableColumnBo apiTableColumnBo : apiTableBo.getColumnList()) {
                                //列编码
                                String columnCode = apiTableColumnBo.getColumnCode();
                                if (StringUtils.isNotEmpty(columnCode)) {
                                    columnCode = columnCode.toLowerCase();
                                }
                                Object object = null;
                                try {
                                    object = rsTableInfo.getObject(columnCode);
                                } catch (Exception e) {
                                    logger.error("获取表：{}字段：{}值出错", tableCode, columnCode);
                                }
                                if (object != null && object.toString()
                                    .length() >= 4000) {
                                    hasExtraData = true;
                                    break;
                                }
                            }
                            if (hasExtraData) {
                                insertScript.append("DECLARE\r\n");
                            }
                            for (ApiTableColumnBo apiTableColumnBo : apiTableBo.getColumnList()) {
                                //列编码
                                String columnCode = apiTableColumnBo.getColumnCode();
                                if (StringUtils.isNotEmpty(columnCode)) {
                                    columnCode = columnCode.toLowerCase();
                                }
                                Object object = null;
                                try {
                                    object = rsTableInfo.getObject(columnCode);
                                } catch (Exception e) {
                                    logger.error("获取表：{}字段：{}值出错", tableCode, columnCode);
                                }
                                if (object != null && object.toString()
                                    .length() >= 4000) {
                                    extraLong.append(columnCode + "Clob clob:='" + object + "';\r\n");
                                    extraLongObj.put(columnCode, columnCode + "Clob");
                                }
                            }
                            if (hasExtraData) {
                                extraLong.append("BEGIN\r\n");
                                insertScript.append(extraLong.toString());
                            }
                            insertScript.append("insert into " + tableCode.toUpperCase() + " (");
                        }
                        ii = 0;
                        LinkedList<String> columnList = new LinkedList<>();
                        for (ApiTableColumnBo apiTableColumnBo : apiTableBo.getColumnList()) {
                            //列编码
                            String columnCode = apiTableColumnBo.getColumnCode();
                            if (StringUtils.isNotEmpty(columnCode)) {
                                columnCode = columnCode.toLowerCase();
                            }
                            columnList.add(columnCode);
                            if (databaseType == EnumDatabaseType.MYSQL) {
                                if (ii == 0) {
                                    insertScript.append("`" + columnCode + "`");
                                } else {
                                    insertScript.append(",`" + columnCode + "`");
                                }
                            } else if (databaseType == EnumDatabaseType.ORACLE) {
                                if (ii == 0) {
                                    insertScript.append(columnCode);
                                } else {
                                    insertScript.append("," + columnCode);
                                }
                            }
                            ii++;
                        }
                        insertScript.append(") values(");
                        ii = 0;
                        for (String column : columnList) {
                            String defaultVal = getDefaultVal(column, apiTableBo.getColumnList());
                            if ("".equals(defaultVal)) {
                                defaultVal = " ";
                            }
                            Object object = null;
                            try {
                                object = rsTableInfo.getObject(column);
                            } catch (Exception e) {
                                logger.error("获取表：{}字段：{}值出错", tableCode, column);
                            }
                            if (ii == 0) {
                                if (object == null && object == "") {
                                    insertScript.append("" + defaultVal);
                                } else {
                                    if (object instanceof Date && EnumDatabaseType.ORACLE == databaseType) {
                                        Date date = (Date) object;
                                        String dateStr = DateUtil.getDate(date, "yyyy-MM-dd HH:mm:ss");
                                        insertScript.append("TO_TIMESTAMP('" + dateStr + "', 'yyyy-MM-dd HH24:MI:SS')");
                                    } else if (object instanceof byte[]) {
                                        byte[] bytes = (byte[]) object;
                                        if (EnumDatabaseType.ORACLE == databaseType) {
                                            insertScript.append(bytesToHexString(bytes));
                                        } else {
                                            insertScript.append("0x" + bytesToHexString(bytes));
                                        }
                                    } else {
                                        if (extraLongObj.containsKey(column)
                                            && EnumDatabaseType.ORACLE == databaseType) {
                                            insertScript.append(extraLongObj.get(column));
                                        } else {
                                            if (object instanceof Boolean) {
                                                boolean value = (Boolean) object;
                                                int intVal = 0;
                                                if (value) {
                                                    intVal = 1;
                                                }
                                                insertScript.append(intVal);
                                            } else {
                                                insertScript.append("'" + object + "'");
                                            }
                                        }
                                    }
                                }
                            } else {
                                if (object == null || object == "") {
                                    insertScript.append("," + defaultVal);
                                } else {
                                    if (object instanceof Date && EnumDatabaseType.ORACLE == databaseType) {
                                        Date date = (Date) object;
                                        String dateStr = DateUtil.getDate(date, "yyyy-MM-dd HH:mm:ss");
                                        insertScript.append(",TO_DATE('" + dateStr + "', 'SYYYY-MM-DD HH24:MI:SS')");
                                    } else if (object instanceof byte[]) {
                                        byte[] bytes = (byte[]) object;
                                        if (EnumDatabaseType.ORACLE == databaseType) {
                                            insertScript.append("," + bytesToHexString(bytes));
                                        } else {
                                            insertScript.append(",0x" + bytesToHexString(bytes));
                                        }
                                    } else {
                                        if (extraLongObj.containsKey(column)
                                            && EnumDatabaseType.ORACLE == databaseType) {
                                            insertScript.append("," + extraLongObj.get(column));
                                        } else {
                                            if (object instanceof Boolean) {
                                                boolean value = (Boolean) object;
                                                int intVal = 0;
                                                if (value) {
                                                    intVal = 1;
                                                }
                                                insertScript.append("," + intVal);
                                            } else {
                                                insertScript.append(",'" + object + "'");
                                            }
                                        }
                                    }
                                }
                            }
                            ii++;
                        }
                        insertScript.append(");\r\n");
                        if (CollectionUtil.isNotEmpty(extraLongObj) && EnumDatabaseType.ORACLE == databaseType) {
                            insertScript.append("END;\r\n");
                            insertScript.append("/\r\n");
                        }
                        insertScripts.append(insertScript.toString());
                    }
                    FileUtils.mergeContentToFile(outputInsertScriptPath, insertScripts.toString());
                }
                //生成insert语句
                FileUtils.mergeContentToFile(outputInsertScriptPath, "\r\n\r\ncommit;\r\n");
                i++;
            }
        } catch (Exception e) {
            logger.error("生成数据脚本出错：", e.getMessage());
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

    public String bytesToHexString(byte[] bArr) {
        StringBuffer sb = new StringBuffer(bArr.length);
        String sTmp;

        for (int i = 0; i < bArr.length; i++) {
            sTmp = Integer.toHexString(0xFF & bArr[i]);
            if (sTmp.length() < 2)
                sb.append(0);
            sb.append(sTmp.toUpperCase());
        }

        return sb.toString();
    }

    /**
     * 获取默认值
     *
     * @param column
     * @param columnList
     * @return
     */
    private String getDefaultVal(String column, List<ApiTableColumnBo> columnList) {
        if (CollectionUtil.isEmpty(columnList)) {
            return "";
        }
        for (ApiTableColumnBo columnBo : columnList) {
            if (column.equals(columnBo.getColumnCode())) {
                return columnBo.getDefaultVal();
            }
        }
        return "";
    }

    /**
     * 获取表格前缀
     *
     * @param tablePrefix
     * @param apiTables
     * @return
     */
    private List<String> getTablePrefixs(String tablePrefix, List<ApiTableBo> apiTables) {
        List<String> tablePrefixs = new ArrayList<>();
        if (StringUtils.isNotEmpty(tablePrefix)) {
            tablePrefixs.add(tablePrefix);
        } else {
            if (CollectionUtil.isNotEmpty(apiTables)) {
                for (ApiTableBo apiTableBo : apiTables) {
                    String tableCode = apiTableBo.getTableCode();
                    String prefix = tableCode.split("_")[0];
                    if (!tablePrefixs.contains(prefix)) {
                        tablePrefixs.add(prefix);
                    }
                }
            }
        }
        return tablePrefixs;
    }

    /**
     * 生成数据脚本头部信息
     *
     * @param scriptVo
     */
    private void writeHeaderContent(ApiDatabaseInsertScriptVo scriptVo, EnumDatabaseType databaseType) {

        StringBuilder sb = new StringBuilder("-- --------------------\r\n");
        sb.append("-- 更新时间:" + scriptVo.getExportDate() + "\r\n");
        sb.append("-- 负责人:" + scriptVo.getAuthor() + "\r\n");
        sb.append("-- 更新内容:" + scriptVo.getExportComment() + "\r\n");
        //TODO 变量设置
        sb.append("-- --------------------\r\n");
        if (databaseType == EnumDatabaseType.MYSQL) {
            sb.append("SET autocommit = 0;\r\n");
        }
        FileUtils.writeToFile(outputInsertScriptPath, sb.toString(), "utf-8");
    }

    /**
     * Oracle字段生成
     *
     * @param sb
     * @param columnList
     * @param indexEmpty
     */
    private void formatOracleColumnInfo(StringBuilder sb, List<ApiTableColumnBo> columnList, boolean indexEmpty) {
        int i = 0;
        for (ApiTableColumnBo apiTableColumn : columnList) {
            sb.append(" \"" + apiTableColumn.getColumnCode()
                .toUpperCase() + "\"");
            //字段类型、字段长度
            String columnLength = apiTableColumn.getColumnLength();
            if (StringUtils.isNotEmpty(columnLength)) {
                if (apiTableColumn.getColumnType()
                    .equalsIgnoreCase("bigint") || apiTableColumn.getColumnType()
                    .equalsIgnoreCase("int") || apiTableColumn.getColumnType()
                    .equalsIgnoreCase("smallint") || apiTableColumn.getColumnType()
                    .equalsIgnoreCase("tinyint")) {
                    sb.append(" " + CommonUtil.mysqlType2OracleType(apiTableColumn.getColumnType()));
                } else {
                    sb.append(" " + CommonUtil.mysqlType2OracleType(apiTableColumn.getColumnType()) + "("
                        + apiTableColumn.getColumnLength() + ")");
                }
            } else {
                sb.append(" " + CommonUtil.mysqlType2OracleType(apiTableColumn.getColumnType()));
            }
            if (StringUtils.isNotEmpty(apiTableColumn.getDefaultVal())) {
                if (apiTableColumn.getColumnType()
                    .equalsIgnoreCase("varchar") || apiTableColumn.getColumnType()
                    .equalsIgnoreCase("char")) {
                    sb.append(" DEFAULT('" + apiTableColumn.getDefaultVal() + "')");
                } else if (apiTableColumn.getColumnType()
                    .equalsIgnoreCase("date") || apiTableColumn.getColumnType()
                    .equalsIgnoreCase("datetime") || apiTableColumn.getColumnType()
                    .equalsIgnoreCase("timestamp") || apiTableColumn.getColumnType()
                    .equalsIgnoreCase("current_timestamp")) {
                    Date date = DateUtils.parseDate(apiTableColumn.getDefaultVal());
                    if (date == null) {
                        date = new Date();
                    }
                    String dateStr = DateUtil.getDate(date, "yyyy-MM-dd HH:mm:ss");
                    sb.append(" DEFAULT TO_TIMESTAMP('" + dateStr + "', 'yyyy-MM-dd HH24:MI:SS')");
                } else {
                    sb.append(" DEFAULT(" + apiTableColumn.getDefaultVal() + ")");
                }
            }
            //是否为null
            if ("否".equals(apiTableColumn.getColumnIsNull())) {
                sb.append(" NOT NULL");
            }
            if (i != columnList.size() - 1) {
                sb.append(",\r\n");
            } else {
                sb.append("\r\n");
            }
            i++;
        }
    }

    /**
     * 生成数据库表缩写
     *
     * @param apiTables
     */
    @Override
    public void generateTableAbbreviation(List<ApiTableBo> apiTables, Long databaseId) {
        List<ApiTableAbbreviationDo> apiTableAbbreviationDos = new ArrayList<>();
        for (ApiTableBo apiTableBo : apiTables) {
            //如果已存在则不保存
            ApiTableAbbreviationDo checkDo = apiTableAbbreviationDao.findByTableCode(apiTableBo.getTableCode(),
                databaseId);
            if (checkDo != null) {
                continue;
            }
            String tableCodeAbridge = getTableCodeAbridge(apiTableBo.getTableCode());
            ApiTableAbbreviationDo apiTableAbbreviationDo = new ApiTableAbbreviationDo();
            apiTableAbbreviationDo.setDatabaseId(databaseId);
            apiTableAbbreviationDo.setTableAbbreviation(tableCodeAbridge);
            apiTableAbbreviationDo.setTableCode(apiTableBo.getTableCode());
            apiTableAbbreviationDo.setTableName(apiTableBo.getTableDesc());
            apiTableAbbreviationDo.setCreateBy(SessionUtil.getSessionUserId());
            apiTableAbbreviationDo.setUpdateBy(SessionUtil.getSessionUserId());
            apiTableAbbreviationDo.setCreateDate(new Date());
            apiTableAbbreviationDo.setUpdateDate(new Date());
            apiTableAbbreviationDos.add(apiTableAbbreviationDo);
        }
        if (CollectionUtil.isNotEmpty(apiTableAbbreviationDos)) {
            apiTableAbbreviationDao.insertBatch(apiTableAbbreviationDos);
        }
    }
}
